﻿#pragma once

#include "BaseTimer.h"

#include <queue>
#include <unordered_map>
#include <mutex>
#include <memory>

namespace LH {
	inline namespace V1
	{

		/*
		 * 使用STL容器实现最小堆定时器
		 * STL容器priority_queue实现即为最小堆方式
		 */
		class Timer : public BaseTimer
		{
		public:
			bool reschedule(TimerID id,
				std::chrono::milliseconds msecs,
				bool repeat = false) final override;

			void cancel(TimerID id) final override;

			void cancelAll() final override;

		protected:
			// 创建新的定时任务
			TimerID doSchedule(TimerListener listener,
				std::chrono::milliseconds msecs,
				std::chrono::milliseconds delay,
				bool repeat,
				Datum repeatMode = Datum::NOT_SET) final override;

			// 触发定时任务
			// 返回 true,有执行定时任务；false,没有定时任务
			bool fireTimer(const std::chrono::steady_clock::time_point& tpNow) final override;

			// 计算超时
			// 返回 -1，没有定时任务 
			int32_t calculateTimeout(const std::chrono::steady_clock::time_point& now) final override;

		private:
			// 这里用的互斥锁。
			// 开发中可以根据使用场景使用自旋锁/读写锁代替互斥锁
			mutable std::mutex m_mtx;

			struct Comparator //仿函数,比较器
			{
				bool operator() (const std::weak_ptr<TimerNode>& a,
					const std::weak_ptr<TimerNode>& b) const
				{
					auto spN1 = a.lock();
					auto spN2 = b.lock();
					if (spN1 && spN2)
					{
						return spN1->tp > spN2->tp; //小顶堆
					}
					else
					{
						return false;
					}
				}
			};
			using TimerNodesQueue = std::priority_queue<
				std::weak_ptr<TimerNode>,
				std::vector<std::weak_ptr<TimerNode>>,
				Comparator>;
			TimerNodesQueue m_timerNodeQueue;

			using TimerNodesHashMap = std::unordered_map<TimerID,
				std::shared_ptr<TimerNode>>;
			TimerNodesHashMap m_timerNodeHashMap;
		};

	}
}// namespace LH
